package com.qinyi.framework.config;

import com.qinyi.framework.shiro.realm.UserRealm;
import com.qinyi.framework.shiro.web.filter.Captcha.CaptchaValidateFilter;
import com.qinyi.framework.shiro.web.online.OnlineSessionFilter;
import net.sf.ehcache.CacheManager;
import org.apache.commons.io.IOUtils;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.config.ConfigurationException;
import org.apache.shiro.io.ResourceUtils;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.Cookie;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author wangan on 2019/6/3
 * @description
 */
@Configuration
public class ShiroConfig {

	// 验证码开关
	@Value("${shiro.user.captchaEnabled}")
	private boolean captchaEnabled;

	// 验证码类型
	@Value("${shiro.user.captchaType}")
	private String captchaType;

	// 设置Cookie的域名
	@Value("${shiro.cookie.domain}")
	private String domain;

	// 设置cookie的有效访问路径
	@Value("${shiro.cookie.path}")
	private String path;

	// 设置HttpOnly属性
	@Value("${shiro.cookie.httpOnly}")
	private boolean httpOnly;

	// 设置Cookie的过期时间，秒为单位
	@Value("${shiro.cookie.maxAge}")
	private int maxAge;

	// 登录地址
	@Value("${shiro.user.loginUrl}")
	private String loginUrl;

	@Bean
	public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
		ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
		factoryBean.setSecurityManager(securityManager);
		factoryBean.setLoginUrl(loginUrl); //设置登录页面
		HashMap<String, String> filterMap = new HashMap<>();
		// 对静态资源设置匿名访问
		filterMap.put("/favicon.ico**", "anon");
		filterMap.put("/ruoyi.png**", "anon");
		filterMap.put("/css/**", "anon");
		filterMap.put("/docs/**", "anon");
		filterMap.put("/fonts/**", "anon");
		filterMap.put("/img/**", "anon");
		filterMap.put("/ajax/**", "anon");
		filterMap.put("/js/**", "anon");
		filterMap.put("/ruoyi/**", "anon");
		filterMap.put("/druid/**", "anon");
		filterMap.put("/captcha/captchaImage**", "anon");
		filterMap.put("/login", "anon,captchaValidate");
		///设置过滤器
		Map<String, Filter> filters = new LinkedHashMap<>();
		filters.put("onlineSession", onlineSessionFilter());
		filters.put("captchaValidate", captchaValidateFilter());
		factoryBean.setFilters(filters);
		filterMap.put("/**", "onlineSession");
		factoryBean.setFilterChainDefinitionMap(filterMap);
		return factoryBean;
	}


	@Bean
	public SecurityManager securityManager(UserRealm userRealm) {
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
		//ream
		securityManager.setRealm(userRealm);
		//记住我
		securityManager.setRememberMeManager(rememberMeManager());
		return securityManager;
	}

//	@Bean
//	public OnlineWebSessionManager sessionManager() {
//		OnlineWebSessionManager sessionManager = new OnlineWebSessionManager();
//		sessionManager.setSessionFactory(sessionFactory());
//		sessionManager.setSessionDAO(sessionDAO());
//		return sessionManager;
//	}
//
//
//	public OnlineSessionFactory sessionFactory() {
//		OnlineSessionFactory factory = new OnlineSessionFactory();
//		return factory;
//	}
//
//	@Bean
//	public OnlineSessionDAO sessionDAO() {
//		OnlineSessionDAO sessionDAO = new OnlineSessionDAO();
//		return sessionDAO;
//	}


	@Bean
	public OnlineSessionFilter onlineSessionFilter() {
		OnlineSessionFilter filter = new OnlineSessionFilter();
		filter.setLoginUrl(loginUrl);
		return filter;
	}

	@Bean
	public CaptchaValidateFilter captchaValidateFilter() {
		CaptchaValidateFilter filter = new CaptchaValidateFilter();
		filter.setCaptchaEnabled(captchaEnabled);
		filter.setCaptchaType(captchaType);
		return filter;
	}


	public CookieRememberMeManager rememberMeManager() {
		CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
		cookieRememberMeManager.setCookie(rememberMeCookie());
		return cookieRememberMeManager;
	}

	protected Cookie rememberMeCookie() {
		Cookie cookie = new SimpleCookie("rememberMe");
		cookie.setDomain(domain);
		cookie.setPath(path);
		cookie.setHttpOnly(httpOnly);
		cookie.setMaxAge(maxAge * 24 * 60 * 60);
		return cookie;
	}

	@Bean
	public UserRealm userRealm(EhCacheManager ehCacheManager) {
		UserRealm userRealm = new UserRealm();
		userRealm.setCacheManager(ehCacheManager);
		return userRealm;
	}

	@Bean
	public EhCacheManager ehCacheManager() {
		CacheManager cacheManager = CacheManager.getCacheManager("ruoyi");
		EhCacheManager em = new EhCacheManager();
		if (cacheManager == null) {
			em.setCacheManager(new CacheManager(getCacheManagerConfigFileInputStream()));
			return em;
		} else {
			em.setCacheManager(cacheManager);
		}
		return em;
	}

	private InputStream getCacheManagerConfigFileInputStream() {
		String filePath = "classpath:ehcache/ehcache-shiro.xml";
		InputStream inputStream = null;
		try {
			inputStream = ResourceUtils.getInputStreamForPath(filePath);
			byte[] bytes = IOUtils.toByteArray(inputStream);
			inputStream = new ByteArrayInputStream(bytes);
			return inputStream;
		} catch (IOException e) {
			throw new ConfigurationException("Unable to obtain input stream for cacheManagerConfigFile [" + filePath + "]", e);
		} finally {
			IOUtils.closeQuietly(inputStream);
		}
	}

}
